﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.Mvc;
using CultuRAM.DAL;
using CultuRAM.Models;
using PagedList;

namespace CultuRAM.Controllers
{
    [Authorize]
    public class EventPropertyValuesController : Controller
    {
        //private readonly UnitOfWork _unitOfWork = new UnitOfWork();
        private readonly UnitOfWork _unitOfWork = EventController._unitOfWork;
        private readonly CacheMode _cacheMode = EventController._CacheMode;

        //private static string _msgInfo, _msgSuccess, _msgWarning, _msgError;

        // GET: /EventPropertyValues/Default

        public PartialViewResult Default()
        {
            return PartialView("_Default");
        }

        // GET: /EventPropertyValues/

        public PartialViewResult IndexPv(int page, int idEvent)
        {

            var lista = GetListPropValuesByEventIdPaged(idEvent, _cacheMode.Active, page);

            ViewBag.idEv = idEvent;

            return PartialView("_Index", lista);

            /*
            var list = GetListPropValuesByEventIdPaged(idEvent, page);
            if (list == null || list.Count == 0)
            {
                list = GetListPropValuesByEventCache(idEvent, page);
            }
            list.OrderBy(o => o.EventProperty.Name);
            ViewBag.idEv = idEvent;      
            return PartialView("_Index", list.ToPagedList(page, 7));*/
        }


        // GET: /EventPropertyValues/Create

        public PartialViewResult CreatePv(int idEvent = 0)
        {
            var ev = _unitOfWork.EventRepository.GetByID(idEvent);

            EventPropertyValue lastOrDefault;

            if (!_cacheMode.Active)
            {
                lastOrDefault = _unitOfWork.EventPropertyValueRepository.Get().LastOrDefault();
            }
            else
            {
                lastOrDefault = _cacheMode.EventPropValuesList.Any() ?
                    _cacheMode.EventPropValuesList.ToList().LastOrDefault() :
                    _unitOfWork.EventPropertyValueRepository.Get().LastOrDefault();
            }

            var evpLastId = lastOrDefault != null ? lastOrDefault.PropertyValueId + 1 : 1;

            var evp = new EventPropertyValue {PropertyValueId = evpLastId, EventId = idEvent, Shadow = false};
 

            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(idEvent);
            ViewBag.EventStates = PopulateEventStateDropDownList(null);
            ViewBag.Places = PopulateEventPlaceDropDownList(null);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(null);
            ViewBag.Targets = PopulateTargetDropDownList(null);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            var ms = ModelState.IsValid;

            ViewBag.Class = "alert alert-success";
            return PartialView("Create", evp);
        }


        // POST: /EventPropertyValues/Create

        [HttpPost]
        public PartialViewResult CreatePv(EventPropertyValue eventpropertyvalue)
        {
           
            var evTemp = _cacheMode.EventsList.ToList().FirstOrDefault(ev => ev.EventId == eventpropertyvalue.EventId);
            var proTemp = _unitOfWork.EventPropertyRepository.GetByID(eventpropertyvalue.EventPropertyId);

            eventpropertyvalue.Event = evTemp;
            eventpropertyvalue.EventProperty = proTemp;

            if (ModelState.IsValid)
            {
                try
                {
                    if (_cacheMode.Active)
                    {
                        if (_cacheMode.EventPropValuesList.Any(
                                    item => item.EventProperty.PropertyId == eventpropertyvalue.EventPropertyId))
                        {
                            ViewBag.MsgError = "A propriedade escolhida já existe!";
                            ViewBag.Class = String.Empty;
                            return PartialView("_Default");
                        }

                        _cacheMode.EventPropValuesList.Add(eventpropertyvalue);
     
                    }
                    else
                    {
                        if (_unitOfWork.EventPropertyValueRepository.Get().Any(
                                    item => item.EventProperty.PropertyId == eventpropertyvalue.EventPropertyId &&
                                            item.EventId == eventpropertyvalue.EventId))
                        {
                            ViewBag.MsgError = "A propriedade escolhida já existe!";
                            ViewBag.Class = String.Empty;
                            return PartialView("_Default");
                        }

                        eventpropertyvalue.Event = _unitOfWork.EventRepository.GetByID(eventpropertyvalue.EventId);
                        _unitOfWork.EventPropertyValueRepository.Insert(eventpropertyvalue);
                        _unitOfWork.Save();
                    }

                    ViewBag.MsgSuccess = "A propriedade foi registada com Sucesso!";
                    ViewBag.Class = String.Empty;
                    return PartialView("_Default");

                }

                catch (DataException ex)
                {
                    var error = ex;
                }
            }

            var evId = eventpropertyvalue.EventId == 0 ? eventpropertyvalue.Event.EventId : eventpropertyvalue.EventId;

            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(evId);

            ViewBag.EventStates = PopulateEventStateDropDownList(null);
            ViewBag.Places = PopulateEventPlaceDropDownList(null);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(null);
            ViewBag.Targets = PopulateTargetDropDownList(null);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            return PartialView("Create", eventpropertyvalue);
        }

        // GET: /EventPropertyValues/Edit/5

        public PartialViewResult EditPv(int id = 0)
        {
            if (id == 0)
            {
                ViewBag.MsgWarning = new MvcHtmlString("<b>ATENÇÃO:</b><br> Selecione a propriedade que pretende editar, clicando numa das linhas da tabela!");
                return PartialView("_Default");
            }

            EventPropertyValue eventpropertyvalue = null;

            if (_cacheMode.Active)
            {
                foreach (var item in _cacheMode.EventPropValuesList.Where(item => item.PropertyValueId == id))
                {
                    eventpropertyvalue = item;
                    break;
                }
            }
            else
            {
                eventpropertyvalue = _unitOfWork.EventPropertyValueRepository.GetByID(id);
            }


            if (eventpropertyvalue == null)
            {
                ViewBag.MsgError = "Ocorreu um erro ao tentar editar a propriedade. Certifique-se que selecionou uma propriedade!";
                return PartialView("_Default");
            }
                
                        
            var evId = eventpropertyvalue.EventId == 0 ? eventpropertyvalue.Event.EventId : eventpropertyvalue.EventId;

            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(evId, eventpropertyvalue.EventProperty.PropertyId);
            ViewBag.EventStates = PopulateEventStateDropDownList(eventpropertyvalue.Value);
            ViewBag.Places = PopulateEventPlaceDropDownList(eventpropertyvalue.Value);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(eventpropertyvalue.Value);
            ViewBag.Targets = PopulateTargetDropDownList(eventpropertyvalue.Value);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            return PartialView("Edit", eventpropertyvalue);
        }


        // POST: /EventPropertyValues/Edit/5

        [HttpPost]
        public PartialViewResult EditPv(EventPropertyValue eventpropertyvalue)
        {
            
            var proTemp = _unitOfWork.EventPropertyRepository.GetByID(eventpropertyvalue.EventProperty.PropertyId);
            var evId = eventpropertyvalue.EventId == 0 ? eventpropertyvalue.Event.EventId : eventpropertyvalue.EventId;
            var ev = new Event();

            if (_cacheMode.Active)
            {
                foreach (var item in _cacheMode.EventsList.Where(item => item.EventId == evId))
                {
                    eventpropertyvalue.Event = item;
                    ev = item;
                }
            }
            else
            {
                foreach (var item in _unitOfWork.EventRepository.Get().Where(item => item.EventId == evId))
                {
                    eventpropertyvalue.Event = item;
                }         
            }        
            
            eventpropertyvalue.EventProperty = proTemp;
            eventpropertyvalue.EventPropertyId = eventpropertyvalue.EventProperty.PropertyId;
            eventpropertyvalue.EventId = evId;

            if (ModelState.IsValid)
            {

                if (_cacheMode.Active)
                {
                    //Alterar a propriedade nas Lista de Propriedades
                    foreach (var item in _cacheMode.EventPropValuesList.Where(item => item.PropertyValueId == eventpropertyvalue.PropertyValueId))
                    {
                        _cacheMode.EventPropValuesList.Remove(item);
                        _cacheMode.EventPropValuesList.Add(eventpropertyvalue);
                        break;
                    }
             
                    //Alterar a propriedade no Evento
                    foreach (var item in ev.PropertyValues.Where(item => item.PropertyValueId == eventpropertyvalue.PropertyValueId))
                    {
                        ev.PropertyValues.Remove(item);
                        ev.PropertyValues.Add(eventpropertyvalue);
                        break;
                    }                                           
                }
                else
                {
                    //var evTemp = _unitOfWork.EventRepository.GetByID(evId);
                    //evTemp.PropertyValues = GetListPropValuesByEvent(evId);

                    _unitOfWork.EventPropertyValueRepository.Update(eventpropertyvalue);
                    _unitOfWork.Save();              
                }

                ViewBag.MsgSuccess = "A propriedade foi alterada com sucesso!";
                return PartialView("_Default");
            }

         
            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(evId, eventpropertyvalue.EventProperty.PropertyId);
            ViewBag.EventStates = PopulateEventStateDropDownList(eventpropertyvalue.Value);
            ViewBag.Places = PopulateEventPlaceDropDownList(eventpropertyvalue.Value);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(eventpropertyvalue.Value);
            ViewBag.Targets = PopulateTargetDropDownList(eventpropertyvalue.Value);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            return PartialView("Edit", eventpropertyvalue);
            
        }

      
        // 
        // GET: /EventPropertyValues/Delete/5

        public PartialViewResult DeletePv(int id = 0)
        {
            if (id == 0)
            {
                ViewBag.MsgWarning = new MvcHtmlString("<b>ATENÇÃO:</b><br> Selecione a propriedade que pretende eliminar, clicando numa das linhas da tabela!");
                return PartialView("_Default");
            }

            EventPropertyValue eventpropertyvalue = null;

            if (_cacheMode.Active)
            {
                foreach (var item in _cacheMode.EventPropValuesList.Where(item => item.PropertyValueId == id))
                {
                    eventpropertyvalue = item;
                    eventpropertyvalue.PropertyValueId = item.PropertyValueId;
                    break;
                }
            }
            else
            {
                eventpropertyvalue = _unitOfWork.EventPropertyValueRepository.GetByID(id);
            }


            if (eventpropertyvalue == null)
            {
                ViewBag.MsgError = "Ocorreu um erro ao tentar eliminar a propriedade. Certifique-se que selecionou uma propriedade!";
                return PartialView("_Default");
            }
       

            var evId = eventpropertyvalue.EventId == 0 ? eventpropertyvalue.Event.EventId : eventpropertyvalue.EventId;
            //var evTemp = _unitOfWork.EventRepository.GetByID(evId);
            //eventpropertyvalue.Event = evTemp;

            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(evId, eventpropertyvalue.EventProperty.PropertyId);
            ViewBag.EventStates = PopulateEventStateDropDownList(eventpropertyvalue.Value);
            ViewBag.Places = PopulateEventPlaceDropDownList(eventpropertyvalue.Value);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(eventpropertyvalue.Value);
            ViewBag.Targets = PopulateTargetDropDownList(eventpropertyvalue.Value);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            return PartialView("Delete", eventpropertyvalue);
        }
       

        // 
        // POST: /EventPropertyValues/Delete/5

        [HttpPost, ActionName("DeletePv")]
        public PartialViewResult DeleteConfirmedPv(EventPropertyValue eventpropertyvalue)
        {
            var proTemp = _unitOfWork.EventPropertyRepository.GetByID(eventpropertyvalue.EventPropertyId);
            var evId = eventpropertyvalue.EventId == 0 ? eventpropertyvalue.Event.EventId : eventpropertyvalue.EventId;

            if (_cacheMode.Active)
            {
                foreach (var item in _cacheMode.EventsList.Where(item => item.EventId == evId))
                {
                    eventpropertyvalue.Event = item;
                }
            }
            else
            {
                foreach (var item in _unitOfWork.EventRepository.Get().Where(item => item.EventId == evId))
                {
                    eventpropertyvalue.Event = item;
                }
            }
             
            eventpropertyvalue.EventProperty = proTemp;
            eventpropertyvalue.EventId = evId;

            if (ModelState.IsValid)
            {

                if (_cacheMode.Active)
                {
                    foreach (var item in _cacheMode.EventPropValuesList.Where(item => item.PropertyValueId == eventpropertyvalue.PropertyValueId))
                    {
                        _cacheMode.EventPropValuesList.Remove(item);
                        break;
                    }
                }
                else
                {
                    //context.Entry(eventpropertyvalue).State = EntityState.Detached;
                    //_unitOfWork.EventPropertyValueRepository.Detached(eventpropertyvalue);
                    _unitOfWork.EventPropertyValueRepository.Delete(eventpropertyvalue.PropertyValueId);
                    _unitOfWork.Save();
                    //return PartialView("_Index", GetListPropValuesByEventPaged(eventpropertyvalue.EventId));
                }
                

                ViewBag.MsgSuccess = "A propriedade foi eliminada com sucesso!";
                return PartialView("_Default");
            }


            ViewBag.EventPropertyIdDdl = PopulatePropertyDropDownList(evId, eventpropertyvalue.EventPropertyId);
            ViewBag.EventStates = PopulateEventStateDropDownList(eventpropertyvalue.Value);
            ViewBag.Places = PopulateEventPlaceDropDownList(eventpropertyvalue.Value);
            ViewBag.WeekDays = PopulateWeekDayDropDownList(eventpropertyvalue.Value);
            ViewBag.Targets = PopulateTargetDropDownList(eventpropertyvalue.Value);
            ViewBag.YesNo = PopulateYesNoDropDownList();

            return PartialView("Delete", eventpropertyvalue);
                    
        }


        //AUXILIARY METHODS /////////////////////////////////////////////////////////

        //Method: List of the Property Values of Event
        public IPagedList<EventPropertyValue> GetListPropValuesByEventIdPaged(int eventId, bool activeCache, int page = 1)
        {
            var epv = _cacheMode.EventPropValuesList.ToList();
            var cb = _cacheMode.Active;
            return activeCache ? _cacheMode.EventPropValuesList.Where(x => x.Event.EventId == eventId).OrderBy(o => o.EventProperty.Name).ToPagedList(page, 7)
                : _unitOfWork.EventPropertyValueRepository.Get(filter: x => x.Event.EventId == eventId).OrderBy(o => o.EventProperty.Name).ToPagedList(page, 7);
        }

        //Method: Get the list of all Resources by ID
        public IList<EventPropertyValue> GetListPropValuesByEventId(int eventId, bool activeCache, int page = 1)
        {
            return activeCache ? _cacheMode.EventPropValuesList.Where(x => x.EventId == eventId).ToList().OrderBy(o => o.EventProperty.Name).ToList()
                : _unitOfWork.EventPropertyValueRepository.Get(filter: x => x.EventId == eventId).OrderBy(o => o.EventProperty.Name).ToList();
        }

/*

        //Method: List of the Property Values of Event
        private List<EventPropertyValue> GetListPropValuesByEvent(int eventId, int page = 1)
        {
            var list = _unitOfWork.EventPropertyValueRepository.Get(x => x.EventId == eventId).OrderBy(o => o.EventProperty.Name);
            return list.ToList();
        }

        //Method: List of the Property Values of Event
        private IPagedList<EventPropertyValue> GetListPropValuesByEventPaged(int eventId, int page = 1)
        {
            var list = _unitOfWork.EventPropertyValueRepository.Get(x => x.EventId == eventId).OrderBy(o => o.EventProperty.Name);
            return list.ToList().ToPagedList(page, 7);
        }
        */

        //Method: List of the Property Values of Event in Cache
        private List<EventPropertyValue> GetListPropValuesByEventCache(int eventId, int page = 1)
        {
            
            //var list = _unitOfWork.EventPropertyValueRepository.Get(x => x.EventId == eventId);
            var list = _cacheMode.EventPropValuesList.ToList().Where(ev => ev.Event.EventId == eventId).OrderBy(o => o.EventProperty.Name);
            
            //var teste = list.ToList().ToPagedList(page, 7);

            return list.ToList();
        }

        //Method: List of the Properties by EventType
        private IList<EventProperty> GetListPropByEventType(int eventId)
        {
            var ev = _unitOfWork.EventRepository.GetByID(eventId);

            if (ev == null)
            {
                ev = _cacheMode.EventsList.FirstOrDefault(e => e.EventId == eventId);
            }

            if (ev != null)
            {
                var evType = _unitOfWork.EventTypeRepository.GetByID(ev.EventType.TypeId);

                var properties = new List<EventProperty>();

                for (var t = evType; t != null; t = t.SuperType)
                {
                    properties.AddRange(t.EventProperties);
                }

                return properties.OrderBy(x => x.Name).ToList();
            }
           
            return null;
        }

        //Method: Populate the DropDownList of Properties of Event
        private SelectList PopulatePropertyDropDownList(int eventId, int? selectedPropertyId = 0)
        {
            var propsEvent = GetListPropByEventType(eventId);
            return selectedPropertyId == 0 || selectedPropertyId == null ? 
                new SelectList(propsEvent, "PropertyId", "Name") : 
                new SelectList(propsEvent, "PropertyId", "Name", selectedPropertyId);
        }

        //Method: Populate the DropDownList of Event States
        private SelectList PopulateEventStateDropDownList(string selectedState)
        {
            var states = _unitOfWork.EventStateRepository.GetList().OrderBy(x => x.State);
            return String.IsNullOrEmpty(selectedState) ?
                new SelectList(states, "State", "State") : 
                new SelectList(states, "State", "State", selectedState);
        }

        //Method: Populate the DropDownList of Palces
        private SelectList PopulateEventPlaceDropDownList(string selectedPlace)
        {
            var places = _unitOfWork.PlaceRepository.GetList().OrderBy(x => x.NamePlace);
            return String.IsNullOrEmpty(selectedPlace) ?
                new SelectList(places, "NamePlace", "NamePlace") : 
                new SelectList(places, "NamePlace", "NamePlace", selectedPlace);
        }

        //Method: Populate the DropDownList of Target
        private SelectList PopulateTargetDropDownList(string selectTarget)
        {
            var targets = _unitOfWork.TargetRepository.GetList().OrderBy(x => x.TargetName);
            return String.IsNullOrEmpty(selectTarget) ?
                new SelectList(targets, "TargetName", "TargetName") :
                new SelectList(targets, "TargetName", "TargetName", selectTarget);
        }

        //Method: Populate the DropDownList of WeekDays
        private SelectList PopulateWeekDayDropDownList(string selectedWeekDay)
        {
            var weekDays = new List<Tuple<int, string>>
                {
                    new Tuple<int, string>(1, "Domingo"),
                    new Tuple<int, string>(2, "Segunda-feira"),
                    new Tuple<int, string>(3, "Terça-feira"),
                    new Tuple<int, string>(4, "Quarta-feira"),
                    new Tuple<int, string>(5, "Quinta-feira"),
                    new Tuple<int, string>(6, "Sexta-feira"),
                    new Tuple<int, string>(7, "Sábado"),
                };

            return String.IsNullOrEmpty(selectedWeekDay) ?
                new SelectList(weekDays, "Item2", "Item2") :
                new SelectList(weekDays, "Item2", "Item2", selectedWeekDay);
        }

        //Method: Populate the DropDownList of Yes/No
        private SelectList PopulateYesNoDropDownList()
        {

            var items = new List<SelectListItem>
                {
                    new SelectListItem() {Text = "Sim", Value = "Sim"},
                    new SelectListItem() {Text = "Não", Value = "Nao"}
                };

            return new SelectList(items, "Value", "Text");
        }
    }
}